#ifndef D4334637_8DB6_4BA0_96AE_DCDC28958F5A
#define D4334637_8DB6_4BA0_96AE_DCDC28958F5A

#include <iostream>
#include <sys/stat.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string>
#include <cstring>
#include <signal.h>
#include <unistd.h>
#include "Log.hpp"

Log lg;

const int backlog = 10;

enum {
	SOCKET_ERR = 1,
	BIND_ERR,
	LISTEN_ERR,
};

class Sock{
public:
	Sock()
	{}
	~Sock()
	{}
public:
	void Socket()
	{
		sockfd_ = socket(AF_INET,SOCK_STREAM,0);
		if(sockfd_ < 0){
			lg(Fatal,"socket errror,errno:%d,errstring:%s",errno,strerror(errno));
			exit(SOCKET_ERR);
		}
		int opt = 1;
        setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	}
	void Bind(uint16_t& port)
	{
		struct sockaddr_in server;
		memset(&server,0,sizeof(server));
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_family = AF_INET;
		server.sin_port = htons(port);
		int n = bind(sockfd_,(const struct sockaddr*)&server,sizeof(server));
		if(n < 0){
			lg(Fatal,"bind errror,errno:%d,errstring:%s",errno,strerror(errno));
			exit(BIND_ERR);
		}
	}
	void Listen()
	{
		int n = listen(sockfd_,backlog);
		if(n < 0){
			lg(Fatal,"listen errror,errno:%d,errstring:%s",errno,strerror(errno));
			exit(LISTEN_ERR);
		}
	}
	int Accept(std::string* clientip,uint16_t* clientport)
	{
		struct sockaddr_in client;
		socklen_t len = sizeof(client);
		int newfd = accept(sockfd_,(sockaddr*)&client,&len);
		if(newfd < 0){
			lg(Warnning,"accept errror,errno:%d,errstring:%s",errno,strerror(errno));
			//exit(ACCEPT_ERR);
		}
		*clientip = inet_ntoa(client.sin_addr);
		*clientport = ntohs(client.sin_port);
		return newfd;
	}
	void Connect(std::string& serverip,uint16_t& serverport)
	{
		struct sockaddr_in server;
		server.sin_addr.s_addr = inet_addr(serverip.c_str());
		server.sin_port = htons(serverport);
		server.sin_family = AF_INET;
		int n = connect(sockfd_,(sockaddr*)&server,sizeof(server));
		if(n < 0){
			lg(Warnning,"connect errror,errno:%d,errstring:%s",errno,strerror(errno));
			return;
		}
		lg(Info,"connect success");
	}
	void Close()
	{
		close(sockfd_);
	}
	int Fd()
	{
		return sockfd_;
	}
private:
	int sockfd_;
};

#endif /* D4334637_8DB6_4BA0_96AE_DCDC28958F5A */
